use crate::MathUtils::MathUtils;
use crate::Vector2::Vector2;

#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct Point {
    pub x: f64,
    pub y: f64,
}

impl Point {
    pub const ZERO: Point = Point { x: 0.0, y: 0.0 };

    pub fn new(x: f64, y: f64) -> Self {
        Self { x, y }
    }

    pub fn subtract(&self, p: &Point) -> Vector2 {
        Vector2::new(self.x - p.x, self.y - p.y)
    }

    pub fn equal_to(&self, p: &Point, epsilon: Option<f64>) -> bool {
        MathUtils::equal(self.x, p.x, epsilon) && MathUtils::equal(self.y, p.y, epsilon)
    }

    pub fn distance_to_point(&self, p: &Point) -> f64 {
        self.distance_to_point_squared(p).sqrt()
    }

    pub fn distance_to_point_squared(&self, p: &Point) -> f64 {
        let dx = p.x - self.x;
        let dy = p.y - self.y;
        dx * dx + dy * dy
    }

    pub fn translate(&self, v: &Vector2) -> Point {
        Point::new(self.x + v.x, self.y + v.y)
    }

    pub fn move_point(&mut self, offset: &Vector2) -> &mut Self {
        self.x += offset.x;
        self.y += offset.y;
        self
    }

    pub fn add(&mut self, v: &Vector2) -> &mut Self {
        self.x += v.x;
        self.y += v.y;
        self
    }

    pub fn to_array(&self) -> [f64; 2] {
        [self.x, self.y]
    }

    pub fn less(&self, p: &Point) -> bool {
        if self.x == p.x {
            self.y < p.y
        } else {
            self.x < p.x
        }
    }

    // pub fn offset(&self, dis: f64) -> Polygon {}
}
